local moonshine = require"moonshine"

local PI = math.pi
local TWOPI = 2 * PI
local HALFPI = PI / 2

local segments = {sec = 60, min = 60, hour = 24}

local conf = {
	font = {name = "ledfont.otf", size = 96},
	canvassize = 1024,
	padding = 10, linethickness = 5,
	clockscale = 0.55,
	dials = {
		sec  = {radius = 0.98, width = 0.09, segments = segments.sec},
		min  = {radius = 0.88, width = 0.10, segments = segments.min},
		hour = {radius = 0.77, width = 0.16, segments = segments.hour},
	},
	colorback = {0.05, 0.05, 0.05},
	colorbase = {0.40, 0.15, 0.00, 0.15},
	colorfore = {0.80, 0.15, 0.00},
	startangle = -HALFPI, clockwise = true, invertangle = false,
}

local scalefactor
local font
local clocktextwidth, datetextwidth
local clocktextheight, datetextheight
local clocktextscale, datetextscale
local padding
local clocktext, datetext = "888888", "88888888"
local time

local padx, pady
local dials, effect

local startangle, endangle, clockwise, invertangle

local rescaletext = function(width)
	local fontheight = font:getHeight()
	
	local ctw = font:getWidth("######")
	local dtw = font:getWidth("########")
	local ratio = ctw / dtw

	local factor = width / ctw
	padding = factor * conf.padding
	
	clocktextscale  = factor
	clocktextwidth  = clocktextscale * ctw
	clocktextheight = clocktextscale * fontheight

	datetextscale  = ratio * clocktextscale
	datetextwidth  = datetextscale * dtw
	datetextheight = datetextscale * fontheight
end

local generatedial = function(radius, thickness, segments)
	local dia = 2 * radius
	local base = love.graphics.newCanvas(dia, dia)
	love.graphics.setCanvas(base)
	love.graphics.setBlendMode('replace')
	love.graphics.setColor(1, 1, 1)
	love.graphics.circle( "fill", radius, radius, radius, segments * 4 )

	love.graphics.setColor(1, 1, 1, 0)
	love.graphics.circle( "fill", radius, radius, radius - thickness, segments * 4 )
	
	love.graphics.setLineWidth(conf.linethickness)
	local tetha = TWOPI / segments
	local x, y, t
	for i = 1, segments / 2 do
		t = tetha * i
		x, y = radius * math.cos(t), radius * math.sin(t)
		love.graphics.line(radius - x, radius - y, x + radius, y + radius)
	end

	love.graphics.setCanvas()
	return {base = base, radius = radius}
end

local drawnumbers = function(clocktext, datetext, x, y, width, height)
	local textheight = clocktextheight + datetextheight + padding
	y = y + (height - textheight) / 2
	
	love.graphics.print(clocktext, x + (width - clocktextwidth) / 2, y , 0, clocktextscale, clocktextscale)
	love.graphics.print(datetext, x + (width - datetextwidth) / 2, y + clocktextheight + padding, 0, datetextscale, datetextscale)
end

local generatebase = function(size)
	local radius = size / 2
	local dials = {}
	
	for k, v in pairs(conf.dials) do
		dials[k] = generatedial(radius * v.radius, radius * v.width, v.segments)
		dials[k].canvas = love.graphics.newCanvas(size, size)
	end
	
	rescaletext(size * conf.clockscale)
	
	local base = love.graphics.newCanvas(size, size)
	love.graphics.setCanvas(base)
	love.graphics.setBlendMode('alpha')
	love.graphics.setColor(1, 1, 1)
	drawnumbers('######', '########', 0, 0, size, size) -- there's no character with all segments
	drawnumbers('XXXXXX', 'XXXXXXXX', 0, 0, size, size) -- it is #X or 0*
	local x
	for k, v in pairs(dials) do
		x = radius - v.radius
		love.graphics.draw(v.base, x, x)
	end
	love.graphics.setCanvas()
	dials.back = {base = base, radius = radius}
	
	return dials
end

local rescale = function(width, height)
	local size = conf.canvassize
	if width >= height then
		scalefactor = height / size
		padx, pady = math.floor((width - height) / 2), 0
	else
		scalefactor = width / size
		padx, pady = 0, math.floor((height - width) / 2)
	end

	rescaletext(scalefactor * size * conf.clockscale)
	
	effect = moonshine(moonshine.effects.glow)
	effect.glow.min_luma = 0.2
	--effect.glow.strength = 6
end

function love.load()
	font = love.graphics.newFont(conf.font.name, conf.font.size)
	love.graphics.setFont(font);
	
	local size = conf.canvassize
	dials = generatebase(size)

	rescale(love.graphics.getDimensions())
	love.graphics.setBackgroundColor(conf.colorback)
	
	clockwise, invertangle =  conf.clockwise, conf.invertangle
	startangle, endangle = conf.startangle, (invertangle and 0 or TWOPI) + conf.startangle
end

local drawTimeArc = function(time, name)
	local div = segments[name]
	local t = time[name]
	local dial = dials[name]
	local angle = (invertangle or t ~= 0) and (t * TWOPI) / div or TWOPI
	
	local radius = dials.back.radius
	local x = radius - dial.radius
	local y = radius - dial.radius
	
	love.graphics.setCanvas(dial.canvas)
	
	local a1, a2
	if clockwise then a1, a2 = startangle + angle, endangle
	else              a1, a2 = startangle, endangle - angle end
	
	love.graphics.clear()
	love.graphics.setBlendMode('alpha')
	love.graphics.setColor( 1, 1, 1, 1 )
	love.graphics.draw(dial.base, x, y)
	love.graphics.setColor( 1, 1, 1, 0 )
	love.graphics.setBlendMode('multiply', 'premultiplied')
	love.graphics.arc("fill", radius, radius, 2 * radius, a1, a2, 4)
	
	love.graphics.setCanvas()
end

local drawstage = function()
	local back = dials.back
	love.graphics.setBlendMode('alpha')
	love.graphics.setColor(conf.colorbase)
	love.graphics.draw(back.base, padx, pady, 0, scalefactor, scalefactor)

	local w = 2 * back.radius * scalefactor
	love.graphics.setColor(conf.colorfore)
	drawnumbers(clocktext, datetext, padx, pady, w, w)

	for k, v in pairs(segments) do
		love.graphics.draw(dials[k].canvas, padx, pady, 0, scalefactor, scalefactor)
	end
end

function love.draw()
	effect(drawstage)
	--love.graphics.setColor( 1, 1, 1, 1 )
	--love.graphics.print(love.timer.getFPS(), 10, 10, 0, 0.7, 0.7)
end

local totaldt = 0
function love.update(dt)
	love.timer.sleep(0.08)
	
	totaldt = totaldt + dt
	if totaldt < 1 then return end
	totaldt = totaldt - 1
	time = os.date("*t")
	clocktext = ("%02i%02i%02i"):format(time.hour, time.min, time.sec)
	datetext = ("%04i%02i%02i"):format(time.year, time.month, time.day)

	for k, v in pairs(segments) do drawTimeArc(time, k) end
end

function love.resize(width, height)
	rescale(width, height)
end

function love.keyreleased(key)
   if key == "escape" then
      love.event.quit()
   end
end

